/*
 * @(#)QuartzManager.java
 * 2013-2-26 下午12:20:16
 * 
 *
 * Copyright (c) 2018-2028, HangZhou QiYun InfoTech Co.,Ltd. .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qyxx.platform.sysmng.task.core;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.List;

import javax.servlet.ServletContext;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qyxx.platform.common.utils.spring.SpringContextHolder;
import com.qyxx.platform.sysmng.exception.GsException;
import com.qyxx.platform.sysmng.task.entity.Task;
import com.qyxx.platform.sysmng.task.entity.TaskScheduler;
import com.qyxx.platform.sysmng.task.service.TaskManager;
import com.qyxx.platform.sysmng.task.service.TaskSchedulerManager;

/**
 * 任务调度管理类
 * 
 * @author gxj
 * @version 1.0 2013-2-26 下午12:20:16
 * @since jdk1.6
 */

public class QuartzManager {
	
	private static Logger logger = LoggerFactory.getLogger(QuartzManager.class);
	
	private static final String JOB_GROUP ="DefaultJobGroup";
	
	private static final String TRIGGER_GROUP ="DefaultTriggerGroup";
	
	private static final String JOB_PREFIX = "job_";
	
	private static final String TRIGGER_PREFIX = "trigger_";
	
	private static final String TRUE_1 = "1";
	
	private static TaskManager taskManager = SpringContextHolder.getBean("taskManager");
	
	private static TaskSchedulerManager taskSchedulerManager = SpringContextHolder.getBean("taskSchedulerManager");

	/**
	 * 启动所有调度
	 * 
	 * @param sc
	 */
	public static void startAllTask(ServletContext sc) {
		List<TaskScheduler> tsList = taskSchedulerManager.findAllRunningTaskScheduler();
		if(null!=tsList && !tsList.isEmpty()) {
			Scheduler scheduler = getScheduler(sc);
			for(TaskScheduler ts : tsList) {
				addTask(ts, scheduler);
			}
		}
		logger.info("所有系统任务调度已启动");
	}
	
	/**
	 * 启动任务
	 * 
	 * @param ts
	 * @param sc
	 */
	public static Scheduler startTask(TaskScheduler ts, ServletContext sc) {
		Scheduler scheduler = stopTask(ts, sc);
		addTask(ts, scheduler);
		logger.info("（" + ts.getName() + "）系统任务调度已启动");
		return scheduler;
	}
	
	/**
	 * 停止任务
	 * 
	 * @param ts
	 * @param sc
	 */
	public static Scheduler stopTask(TaskScheduler ts, ServletContext sc) {
		Scheduler scheduler = getScheduler(sc);
		String jkStr = JOB_PREFIX+ts.getName()+ts.getId();
		JobKey jk = new JobKey(jkStr, JOB_GROUP);
		try {
			if(scheduler.checkExists(jk)) {
				scheduler.pauseJob(jk);
				scheduler.deleteJob(jk);
				logger.info("（" + ts.getName() + "）系统任务调度已停止");
			}
			return scheduler;
		} catch (SchedulerException e) {
			throw new GsException("在检查/停止/删除名称为" + jkStr + "的任务调度Job或Trigger时出现异常", e);
		}
	}
	
	/**
	 * 获取任务调度器
	 * 
	 * @param sc
	 * @return
	 */
	private static Scheduler getScheduler(ServletContext sc) {
		StdSchedulerFactory ssf = (StdSchedulerFactory)sc.getAttribute(TaskSchedulerInitListener.QUARTZ_FACTORY_KEY);
		Scheduler scheduler = null;
		try {
			scheduler = ssf.getScheduler();
			return scheduler;
		} catch (SchedulerException e) {
			throw new GsException("从StdSchedulerFactory获取scheduler时出现异常", e);
		}
	}
	
	/**
	 * 添加任务，由调度器调度
	 * 
	 * @param ts
	 * @param scheduler
	 */
	private static void addTask(TaskScheduler ts, Scheduler scheduler) {
		JobDetail job = newJob(TaskJobImpl.class).withIdentity(JOB_PREFIX+ts.getName()+ts.getId(), JOB_GROUP).build();
		Task task = taskManager.getTaskWithoutSession(ts.getTaskId());
		if(null!=task) {
			job.getJobDataMap().put(TaskJobImpl.MAP_KEY, task);
			String exp = buildCronExpression(ts);
		    CronTrigger trigger = newTrigger().withIdentity(TRIGGER_PREFIX+ts.getName()+ts.getId(), TRIGGER_GROUP)
		    							.withSchedule(CronScheduleBuilder.cronSchedule(exp)).build();
		    try {
				scheduler.scheduleJob(job, trigger);
			} catch (SchedulerException e) {
				throw new GsException(ts.getName() + "调度任务" + task.getName() + "出现异常" , e);
			}
		} else {
			throw new GsException("找不到" + ts.getName() + "对应的任务，任务编号为：" + ts.getTaskId());
		}
		logger.info("（" + ts.getName() + "）调度任务已交由系统自动调度");
	}

	/**
	 * 创建cron表达式
	 * 
	 * @param ts
	 * @return
	 */
	private static String buildCronExpression(TaskScheduler ts) {
		String exp = null;
		String type = ts.getDateType();
		String minute = ts.getRunMinute();
		String hour = ts.getRunHour();
		String day = ts.getRunDay();
		String month = ts.getRunMonth();
		String weeks = ts.getRunWeek();
		String second = ts.getRunSecond();

		exp = "0 " + isNull(minute) + isNull(hour);
		if (type.equals("Everyday")) {
			exp = exp + " * * ?";
		} else if (type.equals("Someday")) {
			exp = exp + isNull(day) + "* ?";
		} else if (type.equals("Date")) {
			exp = exp + isNull(day) + isNull(month) + "?";
		} else if (type.equals("Hour")) {
			// "0 15 10 ? * *" Fire at 10:15am every day
			exp = "0 0 0/" + isNull(hour) + " * * ? ";
		} else if (type.equals("Minute")) {
			// "0 0/5 14 * * ?" Fire every 5 minutes starting at 2pm and ending
			// at 2:55pm, every day
			exp = "0 0/" + isNull(minute) + " * * * ? ";
		} else if (type.equals("Second")) {
			// "0 0 12 * * ?" Fire at 12pm (noon) every day
			exp = "0/" + isNull(second) + " * * * * ? ";
		} else if (type.equals("Week")) {
			String weekstr = "";
			try {
				if (TRUE_1.equals(weeks.substring(0, 1)))
					weekstr = "SUN,";
				if (TRUE_1.equals(weeks.substring(1, 2)))
					weekstr = weekstr + "MON,";
				if (TRUE_1.equals(weeks.substring(2, 3)))
					weekstr = weekstr + "TUE,";
				if (TRUE_1.equals(weeks.substring(3, 4)))
					weekstr = weekstr + "WED,";
				if (TRUE_1.equals(weeks.substring(4, 5)))
					weekstr = weekstr + "THU,";
				if (TRUE_1.equals(weeks.substring(5, 6)))
					weekstr = weekstr + "FRI,";
				if (TRUE_1.equals(weeks.substring(6, 7)))
					weekstr = weekstr + "SAT,";

				if (weekstr.equals(""))
					weekstr = "?";
				else
					weekstr = weekstr.substring(0, weekstr.length() - 1);
			} catch (Exception e) {
			}
			exp = exp + "? * " + weekstr;
		} else {
			exp = exp + " * * ?";
		}
		return exp;
	}

	private static String isNull(String str) {
		if (str == null || str.length() == 0)
			return " ";
		else
			return str + " ";
	}

}
